/*******************************************************************
 *   > File Name: mkv210_image.c
 *   > Author: fly
 *   > Create Time: 2021-06-17  4/24  12:03:22 +0800
 *   > Note: 将USB启动时使用的BIN文件制作得到SD启动的Image
 *          计算校验和，添加16字节文件头，校验和写入第8字节处
 *================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define ERR_STR                 strerror(errno)
#define SPL_HEADER_SIZE         (16)
#define SPL_HEADER              "@S5PV210$$$$****"
#define IMG_SIZE                (16*1204)
#define FILE_PATH_LEN_MAX       (256)

char *mk_getCheckSumFile(char *binName)
{
    static char checkSumFileName[FILE_PATH_LEN_MAX] = {0};

    //snprintf(checkSumFileName, FILE_PATH_LEN_MAX, "%s%s", "sd.", binName);
    snprintf(checkSumFileName, FILE_PATH_LEN_MAX, "%s%s",  binName, ".SD.BIN");
    return (char*)checkSumFileName;
}

long mk_getFileLen(FILE* fp)
{
    static long fileLen = 0;
    fseek(fp, 0L, SEEK_END);
    fileLen = ftell(fp);
    fseek(fp, 0L, SEEK_SET);
    return fileLen;
}

int main(int argc, char* argv[])
{
    FILE* fps, *fpd;
    long nbytes, fileLen;
    unsigned int checksum, count; 
    char *BUF = NULL, *pBUF = NULL;
    int i;

    if(argc != 2){
        printf("Usage: %s <bin-file>\n", argv[0]);exit(EXIT_FAILURE);
    }

    /* 打开源BIN文件 */
    fps = fopen(argv[1], "rb");
    if (fps == NULL){
        printf("fopen %s err: %s\n", argv[1], ERR_STR);
        exit(EXIT_FAILURE);
    }

    /* 创建目标BIN文件 */
    fpd = fopen(mk_getCheckSumFile(argv[1]), "w+b");
    if (fpd == NULL){
        printf("fopen %s err: %s\n", mk_getCheckSumFile(argv[1]), ERR_STR);
        fclose(fps);exit(EXIT_FAILURE);
    }

    /* 获取源文件大小 */
    fileLen = mk_getFileLen(fps);
    if(fileLen < (IMG_SIZE - SPL_HEADER_SIZE)){
        count = fileLen;
    }else{
        count = IMG_SIZE - SPL_HEADER_SIZE;
    }

    BUF = (char *)malloc(IMG_SIZE);/* malloc 16KB BUF */
    if (BUF == NULL){
        printf("malloc err: %s\n", ERR_STR);
        fclose(fps);fclose(fpd);
        exit(EXIT_FAILURE);
    }
    memcpy(&BUF[0], SPL_HEADER, SPL_HEADER_SIZE);
    nbytes = fread(BUF+SPL_HEADER_SIZE, 1, count, fps);
    
    /* 计算文件检验和 */
    pBUF = BUF + SPL_HEADER_SIZE;
    for(i = 0, checksum = 0; i< IMG_SIZE - SPL_HEADER_SIZE; i++)
    {
        checksum += (0x000000FF) & *pBUF++;
    }
    pBUF = BUF + 8;
    *((unsigned int *)pBUF) = checksum;

    /* 将校验和源文件写入目标文件 */
    fwrite(BUF, 1, IMG_SIZE, fpd);

    printf("the checksum 0x%08X for %ldbytes, output: %s\n", \
            checksum, fileLen, mk_getCheckSumFile(argv[1]));

    free(BUF);
    fclose(fps);
    fclose(fpd);

    return 0;
}
